<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <script>
      /**
       * Make a map and return a function for checking if a key
       * is in that map.
       *
       *  //map 对象中的[name1,name2,name3,name4]  变成这样的map{name1:true,name2:true,name3:true,name4:true}
       *  并且传进一个key值取值，这里用到策略者模式
       */
      function makeMap(str, expectsLowerCase) {
        var map = Object.create(null); //创建一个新的对象
        var list = str.split(","); //按字符串,分割
        for (var i = 0; i < list.length; i++) {
          map[list[i]] = true; //map 对象中的[name1,name2,name3,name4]  变成这样的map{name1:true,name2:true,name3:true,name4:true}
        }
        return expectsLowerCase
          ? function(val) {
              return map[val.toLowerCase()];
            } //返回一个柯里化函数 toLowerCase转换成小写
          : function(val) {
              return map[val];
            }; //返回一个柯里化函数 并且把map中添加一个 属性建
      }
      //isHTMLTag 函数，验证是否是html中的原始标签
      var isHTMLTag = makeMap(
        "html,body,base,head,link,meta,style,title," +
          "address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section," +
          "div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul," +
          "a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby," +
          "s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video," +
          "embed,object,param,source,canvas,script,noscript,del,ins," +
          "caption,col,colgroup,table,thead,tbody,td,th,tr," +
          "button,datalist,fieldset,form,input,label,legend,meter,optgroup,option," +
          "output,progress,select,textarea," +
          "details,dialog,menu,menuitem,summary," +
          "content,element,shadow,template,blockquote,iframe,tfoot"
      );
      var isSVG = makeMap(
        "svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face," +
          "foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern," +
          "polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",
        true
      );
      //保留标签 判断是不是真的是 html 原有的标签 或者svg标签
      var isReservedTag = function(tag) {
        return isHTMLTag(tag) || isSVG(tag);
      };
      var unknownElementCache = Object.create(null);

      //判断是不是真的是 html 原有的标签，判断是否是浏览器标准标签
      function isUnknownElement(tag) {
        /* istanbul ignore if */
      

        //保留标签 判断是不是真的是 html 原有的标签
        if (isReservedTag(tag)) {
          return false;
        }
        //把标签转化成小写
        tag = tag.toLowerCase();
        /* istanbul ignore if */
        //缓存未知标签
        if (unknownElementCache[tag] != null) {
          //如果缓存有则返回出去
          return unknownElementCache[tag];
        }
        //创建该标签
        var el = document.createElement(tag);
        //判断是否是含有 - 的组件标签
        if (tag.indexOf("-") > -1) {
          // http://stackoverflow.com/a/28210364/1070244
          return (unknownElementCache[tag] =
            el.constructor === window.HTMLUnknownElement ||
            el.constructor === window.HTMLElement);
        } else {
          //正则判断标签是否是HTMLUnknownElement
          return (unknownElementCache[tag] = /HTMLUnknownElement/.test(
            el.toString()
          ));
        }
      }
      console.log(isUnknownElement("html"));
    </script>
  </body>
</html>
